﻿using System;
using System.IO;
using UtilZ.Dotnet.Ex.Model;

namespace UtilZ.Dotnet.Ex.Communication.Net.BMQ
{
    /// <summary>
    /// BMQ消息基类
    /// </summary>
    public abstract class BMQMessageAbs : IBMQMessage
    {
        private readonly ArraySpan<byte> _data = new ArraySpan<byte>();

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="messageType">BMQ消息类型</param>
        public BMQMessageAbs(byte messageType)
        {
            this._messageType = messageType;
        }



        /// <summary>
        /// BMQ消息类型
        /// </summary>
        protected readonly byte _messageType;
        /// <summary>
        /// BMQ消息类型
        /// </summary>
        public byte MessageType
        {
            get { return _messageType; }
        }


        /// <summary>
        /// 消息生成进二进制buffer
        /// </summary>
        /// <param name="buffer">二进制buffer</param>
        public void ToBytes(ArraySpan<byte> buffer)
        {
            int msgSize = this.GetMessageSize();
            buffer.Check(msgSize);

            using (var ms = new MemoryStream(buffer.Array, buffer.Offset, buffer.Length))
            {
                var writer = new BinaryWriter(ms);
                this.WriteMessage(writer);
                ms.Flush();
            }
        }

        /// <summary>
        /// 消息生成进TLV二进制buffer
        /// </summary>
        /// <param name="buffer">二进制buffer</param>
        public void ToTLVBytes(ArraySpan<byte> buffer)
        {
            int msgSize = this.GetMessageSize();
            int size = msgSize + BMQConstant.TLV_HEAD_MIN_SIZE;
            buffer.Check(size);

            using (var ms = new MemoryStream(buffer.Array, buffer.Offset, buffer.Length))
            {
                var writer = new BinaryWriter(ms);
                writer.Write(this._messageType);//tag
                writer.Write(msgSize);//Length
                this.WriteMessage(writer);
                ms.Flush();
            }
        }

        /// <summary>
        /// 将消息写入二进制buffer
        /// </summary>
        /// <param name="writer">消息写器</param>
        protected abstract void WriteMessage(BinaryWriter writer);

        /// <summary>
        /// 获取消息大小
        /// </summary>
        /// <returns>消息大小</returns>
        protected abstract int GetMessageSize();

        /// <summary>
        /// 关闭缓冲区
        /// </summary>
        void IBMQMessage.Close()
        {

        }


        /// <summary>
        /// 读取消息到对象
        /// </summary>
        /// <param name="data">完整消息数据</param>
        public void FromBytes(ArraySpan<byte> data)
        {
            using (var ms = new MemoryStream(data.Array, data.Offset, data.Length))
            {
                var reader = new BinaryReader(ms);
                this.ReadMessage(reader);
            }
        }


        /// <summary>
        /// 读取消息到对象
        /// </summary>
        /// <param name="reader">消息读取器</param>
        protected abstract void ReadMessage(BinaryReader reader);

    }
}
